package cn.edu.sgu.www.mhxysy.redis.repository.impl;

import cn.edu.sgu.www.mhxysy.consts.RedisKeyPrefixes;
import cn.edu.sgu.www.mhxysy.entity.role.RoleAccount;
import cn.edu.sgu.www.mhxysy.mapper.role.RoleAccountMapper;
import cn.edu.sgu.www.mhxysy.redis.RedisUtils;
import cn.edu.sgu.www.mhxysy.redis.repository.RoleDetailRepository;
import cn.edu.sgu.www.mhxysy.util.TimerUtils;
import cn.edu.sgu.www.mhxysy.vo.role.RoleAccountVO;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

/**
 * @author 沐雨橙风ιε
 * @version 1.0
 */
@Slf4j
@Component
public class RoleAccountRepository implements RoleDetailRepository {

    private final RedisUtils redisUtils;
    private final RoleAccountMapper roleAccountMapper;

    public RoleAccountRepository(RedisUtils redisUtils, RoleAccountMapper roleAccountMapper) {
        this.redisUtils = redisUtils;
        this.roleAccountMapper = roleAccountMapper;
    }

    @Override
    public void put(String id, Object value) {
        String key = RedisKeyPrefixes.PREFIX_ROLE_ACCOUNT + id;

        if (value == null) {
            redisUtils.set(key, null);
        } else {
            redisUtils.set(key, JSON.toJSONString(value));
        }

        redisUtils.expire(key, 7, TimeUnit.DAYS);
    }

    @Override
    public RoleAccount selectById(String id) {
        String key = RedisKeyPrefixes.PREFIX_ROLE_ACCOUNT + id;

        if (redisUtils.hasKey(key)) {
            String value = redisUtils.get(key);

            if (value != null) {
                log.debug("命中缓存{}", key);

                return JSON.parseObject(value, RoleAccount.class);
            }

            return null;
        }

        RoleAccount roleAccount = roleAccountMapper.selectById(id);

        put(id, roleAccount);

        return roleAccount;
    }

    @Override
    public void putList(Object value) {
        String key = RedisKeyPrefixes.PREFIX_ROLE_ACCOUNTS;

        redisUtils.set(key, JSON.toJSONString(value), 7, TimeUnit.DAYS);
    }

    @Override
    public List<RoleAccount> selectList() {
        String key = RedisKeyPrefixes.PREFIX_ROLE_ACCOUNTS;

        if (redisUtils.hasKey(key)) {
            String value = redisUtils.get(key);

            log.debug("命中缓存{}", key);

            if (value != null) {
                return JSON.parseArray(value, RoleAccount.class);
            }

            return null;
        }

        List<RoleAccount> list = roleAccountMapper.selectList(null);

        putList(list);

        return list;
    }

    @Override
    public void deleteList() {
        String key = RedisKeyPrefixes.PREFIX_ROLE_ACCOUNTS;

        redisUtils.delete(key);
    }

    @Override
    public void deleteById(String primaryKey) {
        String key = RedisKeyPrefixes.PREFIX_ROLE_ACCOUNT + primaryKey;

        redisUtils.delete(key);
    }

    @Override
    public void delayDoubleDelete(String primaryKey, Consumer<String> consumer) {
        deleteList();
        deleteById(primaryKey);
        deleteCache(primaryKey);

        consumer.accept(primaryKey);

        // 延时双删
        TimerUtils.schedule(new TimerTask() {
            @Override
            public void run() {
                deleteList();
                deleteById(primaryKey);
                deleteCache(primaryKey);
            }
        });
    }

    @Override
    public void cacheRole(String roleId, RoleAccountVO roleAccountVO) {
        String key = RedisKeyPrefixes.PREFIX_ROLE_DETAIL + roleId;

        redisUtils.set(key, JSON.toJSONString(roleAccountVO));
    }

    @Override
    public RoleAccountVO getCache(String roleId) {
        String key = RedisKeyPrefixes.PREFIX_ROLE_DETAIL + roleId;

        if (redisUtils.hasKey(key)) {
            String value = redisUtils.get(key);

            log.debug("命中缓存{}...", key);

            if (value != null) {
                return JSON.parseObject(value, RoleAccountVO.class);
            }

            return null;
        }

        RoleAccountVO details = roleAccountMapper.selectRoleDetails(roleId);

        cacheRole(roleId, details);

        return details;
    }

    @Override
    public void deleteCache(String roleId) {
        String key = RedisKeyPrefixes.PREFIX_ROLE_DETAIL + roleId;

        redisUtils.delete(key);
    }

}